package com.demo.server.impl;

import com.common.Dto.RegisterDTO;
import com.common.Dto.loginDto;
import com.common.Dto.rechargeDTO;
import com.common.LO.FiscoLO;
import com.common.LO.Fisco_accountLO;
import com.common.LO.UserInformationLO;
import com.common.VO.*;
import com.common.commont.Messageconstant;
import com.common.commont.contractAddress;
import com.common.result.Result;
import com.demo.mapper.UserMapper;
import com.demo.mapper.UserPayMapper;
import com.demo.server.UserServer;
import com.tools.Fisco.UserInfo;
import com.tools.Fisco.UserPayInfo;
import com.tools.Fisco.context.context;
import com.tools.Fisco_tools.UserInfo_tools;
import com.tools.untils.Create_;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.fisco.bcos.sdk.transaction.model.exception.ContractException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.util.Set;

@Service
public class userServerImpl implements UserServer {


    private static final Logger log = LoggerFactory.getLogger(userServerImpl.class);
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserPayMapper  userPayMapper;

    /**
     * 用户注册逻辑实现
     * @param registerDto
     * @return Result
     */
    @Override
    public Result<RegisterVO> register(RegisterDTO registerDto) {
        try {
            if(userMapper.select_number(registerDto.getAccount()) != 0 ){
                return Result.error(Messageconstant.Account_Exists);
            }
            Fisco_accountLO fiscoAccount = Create_.create_fisco_account();
            UserInformationLO userInformation = UserInformationLO.builder()
                    .account(registerDto.getAccount())
                    .password(Create_.create_hash256(fiscoAccount.getAccountAddress()+registerDto.getPassword()))
                    .accountStatus(1)
                    .accountRole(1)
                    .name(registerDto.getName())
                    .username(registerDto.getUsername())
                    .phone(registerDto.getPhone())
                    .accountAddress(fiscoAccount.getAccountAddress())
                    .accountPrivatekey(fiscoAccount.getHexPrivateKey())
                    .card(registerDto.getCard())
                    .build();
             userMapper.Insert(userInformation);
            UserInformationLO userInformationLO = userMapper.select_user(userInformation);
            userInformationLO.setPayPassword("NULL");
            log.info(String.valueOf(userInformationLO));

           FiscoLO fiscoSdk = Create_.create_fisco_sdk(userInformation.getAccountPrivatekey());
           String resgiter_Hash = UserInfo_tools.insert(UserInfo.load(contractAddress.InfoAddress, fiscoSdk.getClient(), fiscoSdk.getCryptoKeyPair()), userInformationLO);
           if( resgiter_Hash== null    ){
               return Result.error(Messageconstant.Error_Fisco);
           }
            return Result.sucess(RegisterVO.builder().ReisterHash(resgiter_Hash).build());
        }catch (Exception e){
            log.error(e.getMessage());
            return Result.error(Messageconstant.Error_register);
        }
    }
    @Override
    public LoginVO login(loginDto loginDto) {
            UserInformationLO userInformation = UserInformationLO.builder()
                    .account(loginDto.getAccount())
                    .build();
            userInformation = userMapper.select_user(userInformation);
            String password = Create_.create_hash256(userInformation.getAccountAddress()+loginDto.getPassword());
            if (!password.equals(userInformation.getPassword())){
                return null;
            }
            //数据库审核通过
            FiscoLO fiscoSdk = Create_.create_fisco_sdk(userInformation.getAccountPrivatekey());
        try {
            UserInfo.Struct0 select = UserInfo_tools.select(UserInfo.load(contractAddress.InfoAddress, fiscoSdk.getClient(), fiscoSdk.getCryptoKeyPair()), userInformation.getId());
            if(!select.password.equals(password)){
                throw new Exception(Messageconstant.NOSynchronization);
            }else{
                return LoginVO.builder()
                        .token(userInformation.getId())
                        .name(userInformation.getUsername())
                        .build();
            }
        }catch (Exception e){
            log.error("登录出现问题:"+e.getMessage());
            return null;
        }
    }

    @Override
    public InformationVO getInformation() {
        UserInformationLO userInformation = UserInformationLO.builder()
                .id(context.getCurrtId())
                .build();
        userInformation= userMapper.select_user(userInformation);
        FiscoLO fiscoSdk = Create_.create_fisco_sdk(userInformation.getAccountPrivatekey());
        try {
            UserInfo.Struct0 select = UserInfo_tools.select(UserInfo.load(contractAddress.InfoAddress, fiscoSdk.getClient(), fiscoSdk.getCryptoKeyPair()), context.getCurrtId());
           return  InformationVO.builder()
                    .account(select.account)
                    .preson_name(select.username)
                    .ID_card(select.card)
                    .phone(select.phone)
                    .name(select.name)
                    .build();
        } catch (ContractException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Result<createpaymentVO> createpayment(String paypassword) {
        UserInformationLO userInformation = UserInformationLO.builder()
                .id(context.getCurrtId())
                .build();
        UserInformationLO userInformationLO = userMapper.select_user(userInformation);
        if(userInformationLO != null && !userInformationLO.getId().equals(context.getCurrtId())){
            return Result.error(Messageconstant.NO_account);
        }
        log.error(userInformation.getPayPassword() == null ? "null" : userInformation.getPayPassword());
        if(userInformationLO.getPayPassword() != null){
            return Result.error(Messageconstant.Repeat_creation);
        }
        userInformation.setPayPassword(Create_.create_hash256(userInformation.getAccountAddress() + paypassword));
        userMapper.update(userInformation);
        //创建支付信息表
        userPayMapper.insert(userInformationLO.getAccount());
        //查询用户信息
        String createDate = userPayMapper.select_createDate(userInformationLO.getAccount());
        userInformationLO = userMapper.select_user(userInformation);
        FiscoLO fiscoSdk = Create_.create_fisco_sdk(userInformationLO.getAccountPrivatekey());
        //创建支付密码
        String UpdateHash = UserInfo_tools.update(UserInfo.load(contractAddress.InfoAddress, fiscoSdk.getClient(), fiscoSdk.getCryptoKeyPair()), userInformationLO);
        //创建支付账户
        UserPayInfo create_pay_account = UserPayInfo.load(contractAddress.PayAccount, fiscoSdk.getClient(), fiscoSdk.getCryptoKeyPair());
        TransactionReceipt insert = create_pay_account.insert(userInformationLO.getAccount(), createDate);
        String CreateHash = insert.getTransactionHash();
        createpaymentVO build = createpaymentVO.builder()
                .CreatePayPasswordHash(UpdateHash)
                .CreatePayAccountHash(CreateHash)
                .build();
        return Result.sucess(build);
    }
    @Override
    public Result<rechargeVO> recharge(rechargeDTO recharge) throws ContractException {
        Set<String> validCurrencies = Set.of("CNY", "HKD", "MOP", "USD", "GBP", "EUR", "JPY", "SGD", "AUD");
        String offeringType = recharge.getType();
        //TODO : 没有引入充值渠道
        if(offeringType ==null || !validCurrencies.contains(offeringType)){
            return  Result.error(Messageconstant.money_error);
        }else if (recharge.getNumber() == null){
            return  Result.error(Messageconstant.NO_money);
        }
        UserInformationLO userInformationLO = userMapper.select_user(UserInformationLO.builder().id(context.getCurrtId()).build());
        FiscoLO fiscoSdk = Create_.create_fisco_sdk(userInformationLO.getAccountPrivatekey());
        UserPayInfo load = UserPayInfo.load(contractAddress.PayAccount, fiscoSdk.getClient(), fiscoSdk.getCryptoKeyPair());
        BigInteger number = new BigInteger(recharge.getNumber().toString());
        TransactionReceipt increase = load.increase(userInformationLO.getAccount(), recharge.getType(), number);
        String output = increase.getOutput();
        BigInteger newBalance = new BigInteger(output.substring(2), 16);
        if(newBalance.compareTo(new BigInteger("-1")) ==0 || newBalance.compareTo(new BigInteger("-2")) ==0){
            return  Result.error(Messageconstant.money_error);
        }
        return Result.sucess(rechargeVO.builder().Hash(increase.getTransactionHash()).build());
    }
}

